package net.hands.common.web.html;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
 * 
 * 说明:html解码器
 * <br>
 * <p>这是一个开源的软件，请在LGPLv3下合法使用、修改或重新发布。</p>
 * @author 陈侃(cknet@126.com, 13910090885)
 *         http://code.google.com/p/simpleframework/
 *         http://www.simpleframework.net
 */
public class HtmlDecoder {
   /**
    * 字符map
    */
	private static final Map<String, Character> ENTITY_MAP;

	static {
		final Properties entityReferences = new Properties();
      //加载解编码属性文件
		final InputStream is = HtmlDecoder.class.getResourceAsStream(HtmlDecoder.class
				.getSimpleName() + ".properties");
		if (is == null) {
			throw new IllegalStateException("Entity reference file missing");
		}

		try {
			entityReferences.load(is);
		} catch (final IOException ioex) {
			throw new IllegalStateException(ioex.getMessage());
		} finally {
			try {
				is.close();
			} catch (final IOException e) {
			}
		}

		ENTITY_MAP = new HashMap<String, Character>(entityReferences.size());

		final Enumeration<?> keys = entityReferences.propertyNames();
		while (keys.hasMoreElements()) {
			final String name = (String) keys.nextElement();
			final String hex = entityReferences.getProperty(name);
			final int value = Integer.parseInt(hex, 16);
			ENTITY_MAP.put(name, Character.valueOf((char) value));
		}
	}
   /**
   * 说明:解码 
   * @param html html字符串
   * @return String
   * @update 2012-9-20 下午3:51:12
    */
	public static String decode(final String html) {
		int ndx = html.indexOf('&');
		if (ndx == -1) {
			return html;
		}

		final StringBuilder result = new StringBuilder(html.length());

		int lastIndex = 0;
		final int len = html.length();
		mainloop: while (ndx != -1) {
			result.append(html.substring(lastIndex, ndx));

			lastIndex = ndx;
			while (html.charAt(lastIndex) != ';') {
				lastIndex++;
				if (lastIndex == len) {
					lastIndex = ndx;
					break mainloop;
				}
			}

			if (html.charAt(ndx + 1) == '#') {
				// decimal/hex
				final char c = html.charAt(ndx + 2);
				int radix;
				if ((c == 'x') || (c == 'X')) {
					radix = 16;
					ndx += 3;
				} else {
					radix = 10;
					ndx += 2;
				}

				final String number = html.substring(ndx, lastIndex);
				final int i = Integer.parseInt(number, radix);
				result.append((char) i);
				lastIndex++;
			} else {
				// token
				final String encodeToken = html.substring(ndx + 1, lastIndex);
				final Character replacement = ENTITY_MAP.get(encodeToken);
				if (replacement == null) {
					result.append(encodeToken);
				} else {
					result.append(replacement.charValue());
					lastIndex++;
				}
			}
			ndx = html.indexOf('&', lastIndex);
		}
		result.append(html.substring(lastIndex));
		return result.toString();
	}
}